const amqp = require('amqplib');
const sendMail = require('./mail');

// 全局RabbitMQ连接和通道（修正拼写：cannection → connection）
let connection;
let channel;

/**
 * 连接到RabbitMQ
 * @returns {Promise<void>}
 */
const connectToRabbitMQ = async () => {
  // 已连接则直接返回
  if (connection && channel) return;

  try {
    // 1. 确保环境变量 RABBITMQ_URL 协议正确（必须是 amqp: 或 amqps:）
    // 示例正确格式：amqp://admin:clwy1234@localhost:5672
    if (!process.env.RABBITMQ_URL) {
      throw new Error('未配置 RABBITMQ_URL 环境变量');
    }
    if (!process.env.RABBITMQ_URL.startsWith('amqp:')) {
      throw new Error('RABBITMQ_URL 协议错误，需使用 amqp: 或 amqps:');
    }

    // 2. 建立连接（修正拼写：cannection → connection）
    connection = await amqp.connect(process.env.RABBITMQ_URL);
    console.log('RabbitMQ 连接成功');

    // 3. 创建通道
    channel = await connection.createChannel();
    console.log('RabbitMQ 通道创建成功');

    // 4. 声明队列（修正方法名：asserQueue → assertQueue）
    const queueName = 'mail_queue';
    await channel.assertQueue(queueName, {
      durable: true, // 队列持久化（重启后队列不丢失）
    });
    console.log(`队列 ${queueName} 声明成功`);

    // 监听连接关闭事件，自动重连
    connection.on('close', () => {
      console.error('RabbitMQ 连接断开，将尝试重连');
      connection = null;
      channel = null;
      // 延迟1秒重连
      setTimeout(connectToRabbitMQ, 1000);
    });
  } catch (error) {
    console.error('RabbitMQ 连接/初始化失败：', error.message);
    throw error; // 抛出错误，触发上层重试
  }
};

/**
 * 邮件队列生产者（发送消息）
 * @param {Object} msg 消息内容（需包含 to, subject, html 字段）
 */
const mailProducer = async (msg) => {
  try {
    await connectToRabbitMQ(); // 确保已连接

    // 验证消息必要字段
    if (!msg.to || !msg.subject || !msg.html) {
      throw new Error('邮件消息缺少必要字段（to/subject/html）');
    }

    // 发送消息到队列（持久化消息，重启后消息不丢失）
    const queueName = 'mail_queue';
    const success = channel.sendToQueue(queueName, Buffer.from(JSON.stringify(msg)), {
      persistent: true,
    });

    if (success) {
      console.log(`消息发送成功：${JSON.stringify(msg)}`);
    } else {
      throw new Error('消息发送失败，队列已满或连接异常');
    }
  } catch (error) {
    console.error('邮件队列生产者错误：', error.message);
    throw error;
  }
};

/**
 * 邮件队列消费者（接收消息并发送邮件）
 */
const mailConsumer = async () => {
  try {
    await connectToRabbitMQ(); // 确保已连接

    const queueName = 'mail_queue';
    // 消费队列消息
    channel.consume(
      queueName,
      async (msg) => {
        if (!msg) {
          console.error('收到无效消息：', msg);
          return;
        }

        try {
          // 解析消息内容
          const message = JSON.parse(msg.content.toString());
          console.log('收到邮件消息，开始发送：', message.to);

          // 调用发送邮件方法（传入 res 为 null，让 sendMail 抛出错误）
          await sendMail(message.to, message.subject, message.html, null);

          // 消息处理成功后手动确认（确保邮件发送成功才删除消息）
          channel.ack(msg);
          console.log(`邮件发送成功，已确认消息：${message.to}`);
        } catch (error) {
          console.error('邮件发送失败，消息将重新入队：', error.message);
          // 消息处理失败，重新入队（避免消息丢失）
          channel.nack(msg, false, true);
        }
      },
      {
        noAck: false, // 关闭自动确认，手动控制消息确认（确保业务处理完成）
      }
    );

    console.log('邮件消费者已启动，等待消息...');
  } catch (error) {
    console.error('邮件队列消费者错误：', error.message);
    throw error;
  }
};

module.exports = {
  mailConsumer,
  mailProducer,
};
